package sf.database.jdbc.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

public class ByteObjectArrayBINARYType implements TypeHandler<Byte[]> {

    public Byte[] get(ResultSet rs, String colName) throws SQLException {
        return toObjects(rs.getBytes(colName));
    }

    public Byte[] get(ResultSet rs, int index) throws SQLException {
        return toObjects(rs.getBytes(index));
    }

    public Byte[] get(CallableStatement rs, int index) throws SQLException {
        return toObjects(rs.getBytes(index));
    }

    @Override
    public Byte[] get(CallableStatement cs, String parameterName) throws SQLException {
        return toObjects(cs.getBytes(parameterName));
    }

    public Object set(PreparedStatement stat, Object obj, int index) throws SQLException {
        if (null == obj) {
            stat.setNull(index, getSqlType());
        } else {
            if (obj.getClass() == byte[].class) {
                stat.setBytes(index, (byte[]) obj);
            } else if (obj.getClass() == Byte[].class) {
                stat.setBytes(index, toPrimitives((Byte[]) obj));
            }
        }
        return null;
    }

    @Override
    public Object set(CallableStatement cs, Object obj, String parameterName) throws SQLException {
        if (null == obj) {
            cs.setNull(parameterName, getSqlType());
        } else {
            if (obj.getClass() == byte[].class) {
                cs.setBytes(parameterName, (byte[]) obj);
            } else if (obj.getClass() == Byte[].class) {
                cs.setBytes(parameterName, toPrimitives((Byte[]) obj));
            }
        }
        return null;
    }

    @Override
    public void update(ResultSet rs, String columnLabel, Object value) throws SQLException {
        if (value != null) {
            if (value.getClass() == byte[].class) {
                rs.updateBytes(columnLabel, (byte[]) value);
            } else if (value.getClass() == Byte[].class) {
                rs.updateBytes(columnLabel, toPrimitives((Byte[]) value));
            }
        } else {
            rs.updateNull(columnLabel);
        }
    }

    @Override
    public void update(ResultSet rs, int columnIndex, Object value) throws SQLException {
        if (value != null) {
            if (value.getClass() == byte[].class) {
                rs.updateBytes(columnIndex, (byte[]) value);
            } else if (value.getClass() == Byte[].class) {
                rs.updateBytes(columnIndex, toPrimitives((Byte[]) value));
            }
        } else {
            rs.updateNull(columnIndex);
        }
    }

    @Override
    public int getSqlType() {
        return Types.BINARY;
    }

    @Override
    public Class<Byte[]> getDefaultJavaType() {
        return Byte[].class;
    }

    byte[] toPrimitives(Byte[] oBytes) {
        if (oBytes == null) {
            return null;
        }
        byte[] bytes = new byte[oBytes.length];
        for (int i = 0; i < oBytes.length; i++) {
            bytes[i] = oBytes[i];
        }
        return bytes;
    }

    // byte[] to Byte[]
    Byte[] toObjects(byte[] bytesPrim) {
        if (bytesPrim == null) {
            return null;
        }
        Byte[] bytes = new Byte[bytesPrim.length];
        for (int i = 0; i < bytesPrim.length - 1; i++) {
            bytes[i] = bytesPrim[i];// Autoboxing
        }
        return bytes;
    }
}
